open_clientfd {socket} {connect}


description

ν΄λΌμ΄μ–ΈνŠΈκ°€ μ„œλ²„μ—κ²Œ λ©”μ‹œμ§€λ₯Ό μ „λ‹¬ν•˜κΈ° μœ„ν•΄ ν•„μš”ν•œ κ³Όμ • 쀑 socket, connect 뢀뢄을 λž˜ν•‘ν–ˆλ‹€. getaddrinfo(3)의 hint μΈμžμ— μ–΄λ–€ ν”Œλž˜κ·Έλ₯Ό λ‹€λŠ”μ§€ μœ„μ£Όλ‘œ μ½μ–΄λ³΄μž.

/*
 * open_clientfd - Open connection to server at <hostname, port> and
 *     return a socket descriptor ready for reading and writing. This
 *     function is reentrant and protocol-independent.
 *
 *     On error, returns:
 *       -2 for getaddrinfo error
 *       -1 with errno set for other errors.
 */
int open_clientfd(char *hostname, char *port) {
  int clientfd, rc;
  struct addrinfo hints, *listp, *p;

  /* Get a list of potential server addresses */
  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_socktype = SOCK_STREAM; /* Open a connection */
  hints.ai_flags = AI_NUMERICSERV; /* ... using a numeric port arg. */
  hints.ai_flags |= AI_ADDRCONFIG; /* Recommended for connections */
  if ((rc = getaddrinfo(hostname, port, &hints, &listp)) != 0) {
    fprintf(stderr, "getaddrinfo failed (%s:%s): %s\n", hostname, port,
            gai_strerror(rc));
    return -2;
  }

  /* Walk the list for one that we can successfully connect to */
  for (p = listp; p; p = p->ai_next) {
    /* Create a socket descriptor */
    if ((clientfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0)
      continue; /* Socket failed, try the next */

    /* Connect to the server */
    if (connect(clientfd, p->ai_addr, p->ai_addrlen) != -1) break; /* Success */
    if (close(clientfd) < 0) {
      /* Connect failed, try another */  // line:netp:openclientfd:closefd
      fprintf(stderr, "open_clientfd: close failed: %s\n", strerror(errno));
      return -1;
    }
  }

  /* Clean up */
  freeaddrinfo(listp);
  if (!p) /* All connects failed */
    return -1;
  else /* The last connect succeeded */
    return clientfd;
}

flags